#include "AES.h"
#include "CrytoHash.h"
#include <QDataStream>
#include <QCryptographicHash>
#include <QFile>

namespace TWUtils
{
	namespace Cryto
	{
		void AES_128_Encrypt(const QByteArray& data,const QString& saveFilePath,const char* key)
		{
			QFile dat(saveFilePath);
			if(!dat.open(QIODevice::WriteOnly))
				return;

			TWUtils::Cryto::AES aes;
			aes.SetParameters(128);
			aes.StartEncryption((uchar*)key);
			int length = data.size();
			if(length % 16 > 0)
				length = (length / 16 + 1) * 16;
			uchar* out = new uchar[length];
			aes.Encrypt((const uchar*)data.constData(),out,length / 16);
			QByteArray outBytes((char*)out,length);
			delete[] out;
			QDataStream stream(&dat);
			stream << outBytes;
			dat.close();
		}

		void AES_128_Decrypt(QByteArray* output,const QString& saveFilePath,const char* key)
		{
			QFile dat(saveFilePath);
			if(!dat.open(QIODevice::ReadOnly))
				return;

			QDataStream stream(&dat);
			QByteArray b;
			stream >> b;
			dat.close();

			TWUtils::Cryto::AES aes;
			aes.SetParameters(128);
			aes.StartDecryption((uchar*)key);
			int length = b.size();
			char* plainText = new char[length];
			memset(plainText,0,length);
			aes.Decrypt((const uchar*)b.constData(),(uchar*)plainText,length / 16);
			QByteArray p(plainText,qstrlen(plainText));
			*output = p;
		}

		QByteArray hmac_sha1(const QByteArray& key, const QByteArray& data)
		{
			QByteArray normKey;
			if (key.size() > 64)
				normKey = QCryptographicHash::hash(key, QCryptographicHash::Sha1);
			else
				normKey = key; // no need for zero padding ipad and opad are filled with zeros

			unsigned char* K = (unsigned char *)normKey.constData();

			unsigned char ipad[65];
			unsigned char opad[65];

			memset(ipad, 0, 65);
			memset(opad, 0, 65);

			memcpy(ipad, K, normKey.size());
			memcpy(opad, K, normKey.size());

			for (int i = 0; i < 64; ++i) {
				ipad[i] ^= 0x36;
				opad[i] ^= 0x5c;
			}

			QByteArray context;
			context.append((const char *)ipad, 64);
			context.append(data);

			QByteArray sha1 = QCryptographicHash::hash(context, QCryptographicHash::Sha1);

			context.clear();
			context.append((const char *)opad, 64);
			context.append(sha1);

			sha1.clear();

			sha1 = QCryptographicHash::hash(context, QCryptographicHash::Sha1);
			return sha1;
		}
	}
} // namespace TWUtils

